package net.love5z.web.common.velocity;

import java.io.StringWriter;

import javax.servlet.http.HttpServletResponse;

import net.love5z.web.common.velocity.Love5zVelocityView;

import org.apache.velocity.Template;
import org.apache.velocity.context.Context;

public class Love5zVelocityLayoutView extends Love5zVelocityView {

    private final String DEFAULT_LAYOUT_KEY = "layout";
    private final String DEFAULT_LAYOUT_URL = "layout/default.vm";

    private final String VIEW_CONTENT_KEY   = "view_content_place_holder";

    /**
     * Overrides the normal rendering process in order to pre-process the
     * Context, merging it with the screen template into a single value
     * (identified by the value of screenContentKey). The layout template is
     * then merged with the modified Context in the super class.
     */
    protected void doRender(Context context, HttpServletResponse response) throws Exception {

        renderScreenContent(context);

        // Velocity context now includes any mappings that were defined
        // (via #set) in screen content template.
        // The screen template can overrule the layout by doing
        // #set( $layout = "MyLayout.vm" )
        String layoutUrlToUse = (String) context.get(DEFAULT_LAYOUT_KEY);
        if (layoutUrlToUse != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Screen content template has requested layout [" + layoutUrlToUse
                             + "]");
            }
        } else {
            // No explicit layout URL given -> use default layout of this view.
            layoutUrlToUse = this.DEFAULT_LAYOUT_URL;
        }

        mergeTemplate(getTemplate(layoutUrlToUse), context, response);

    }

    /**
     * The resulting context contains any mappings from render, plus screen
     * content.
     */
    private void renderScreenContent(Context velocityContext) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("Rendering screen content template [" + getUrl() + "]");
        }

        StringWriter sw = new StringWriter();
        Template screenContentTemplate = getTemplate(getUrl());
        screenContentTemplate.merge(velocityContext, sw);

        // Put rendered content into Velocity context.
        velocityContext.put(this.VIEW_CONTENT_KEY, sw.toString());
    }
}
